JavaScript is a very forgiving language. It’s easy to write code that runs but has mistakes in it.
In this article, we’ll look at some best practices regarding functions and default parameters.
Use Default Parameter Syntax Rather Than Mutating Function Arguments
Default parameters are useful for handling parameters that may not have a value set for it by passing in an argument.
For instance, we can write the following code to define parameters with default values:
const add = (a, b = 0) => a + b;
In the code above, we defined an add
function with the parameter b
set to 0 by default.
This way, if we don’t pass anything in, we’ll get that b
is set to 0. The default parameter is also set if we pass in any falsy value.
For example, if we call the function as follows:
add(1, false);
add(1);
Then we get the same result, which is 1 since b
is set to 0.
This is shorter than the old way, which is using the ||
operator to set the default value of a parameter that may not have a value set to it, which is the following:
const add = (a, b) => {
b = b || 0;
return a + b;
}
As we can see, the code is longer, and we have to mutate the parameter b
directly so that we can set the default value the parameter. This is longer and mutating variables unnecessarily is bad.
Default parameters have to come after regular parameters. For instance, we should write something like the following if we have multiple parameters:
const add = (a, b = 0, c = 0) => a + b + c;
Then we can call it by writing something like the following:
add(1, false, 2)
and we get 3 as the returned value since b
is set to 0.
Avoid Side Effects With Default Parameters
We can run any code with default parameters. This includes running side effects. However, we shouldn’t do that since we don’t want to mutate outside code within functions.
Side effects make our code harder to follow and test. Therefore, we shouldn’t do that.
For instance, if we have the following code:
let b = 1;
const count = (a = b--) => {
console.log(a);
}
In the code above, we have a function count
that mutates b
in the default parameter. We can see that b
, which is outside the function, is being mutated as we run count
.
Each time we run count
, b
is decremented. So b
is 1 when count
is first run without an argument passed in and the value is assigned to a
. b
isn’t returned before --
is run so that the decremented value isn’t assigned to a
.
However, when we run count
the 2nd time without an argument passed in, we run the code that decrements b
again with the decremented value that’s returned from the first run is returned, so 0 is returned to a
.
And a
is logged as 0. Likewise, when we run it again and again, we get the same result.
Therefore, it’s committing the side effect of mutating the variable b
, which is mutating the value of b
.
If we run count
with an argument, then we get the argument logged.
Always Put Default Parameters Last
Default parameters should be put last so that we can spot them easily. For instance, instead of writing the following code:
const add = (a, b = 0, c, d = 0) => a + b + c + d;
where we have a
and c
without default values and b
and d
with default parameter values, then the ones with default parameters are hard to spot.
Instead, we should write the parameters with default parameters all together as follows:
const add = (a, b, c = 0, d = 0) => a + b + c + d;
Conclusion
Default parameters are great for setting default values for parameters without mutating parameters directly in our code.
We should follow best practices when using the default parameter syntax, which is ordering parameters with default values after regular parameters and not running code with side effects in default parameter code.